package com.apes.fn.scm.dumpComm.service;

import com.apes.fn.scm.dumpComm.model.PublicParam;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.event.Listener;
import com.apes.scm.stock.safetyStock.repository.SafetyStockGapRepository;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.List;
import java.util.Map;

@Service("safetyGapBusinessService")
public class SafetyGapBusinessService {
    @Autowired
    private SafetyGapOperationService safetyGapOperationService;
    @Autowired
    private SafetyStockGapRepository safetyStockGapRepository;
    @Autowired
    private TransactionTemplate transactionTemplate;

    // 异步调用比定时任务快
    @Listener(topic = "event:scm.safetyGapBusinessService.asynAll")
    public void asynAll(SimpleRequest request) {
        this.safeGapTimingDump();
    }

    // 检查间隔超过多久没有运行
    public void regularCheck() {
        String sql = "" +
                "SELECT ROUND((SYSDATE - TO_DATE(TO_CHAR(CREATE_DATE, 'YYYY/MM/DD HH24:MI:SS'),\n" +
                "                                 'YYYY/MM/DD HH24:MI:SS')) * 24 * 60) NO_DATA_GENERATED_TIME\n" +
                "  FROM (SELECT CREATE_DATE\n" +
                "           FROM STOCK_GAP_DISTRIBUTION_INFO T\n" +
                "          WHERE TO_CHAR(EXECUTE_DATA, 'YYYY/MM/DD') =\n" +
                "                TO_CHAR(SYSDATE - 1, 'YYYY/MM/DD')\n" +
                "          ORDER BY CREATE_DATE DESC)\n" +
                " WHERE ROUND((SYSDATE - TO_DATE(TO_CHAR(CREATE_DATE, 'YYYY/MM/DD HH24:MI:SS'),\n" +
                "                                'YYYY/MM/DD HH24:MI:SS')) * 24 * 60) >=\n" +
                "       (SELECT TO_NUMBER(VALUE)\n" +
                "          FROM MAS_BUSINESS_PARAM\n" +
                "         WHERE QUERY_KEY = 'safetyGap') ";
        List<Integer> findNoDataGeneratedTimes = safetyStockGapRepository.findAll(sql);
        if (!findNoDataGeneratedTimes.isEmpty()) {
            this.safeGapTimingDump();
        }
    }



    public synchronized void safeGapTimingDump() {
        // 仅限单线程操作
        PublicParam publicParam = PublicParam.getInstance(null);

        execute(() -> {
            // 执行前判断是否满足需要执行的条件
            boolean continueExecuFlag = safetyGapOperationService.executeBeforeOperation(publicParam);
            if (!continueExecuFlag) return;

            // 初始化调拨范围数据
            safetyGapOperationService.initData();

            // 生成缺口数据
            this.generateGapData(publicParam.getDevelId());

            // 判断是否满足继续执行的条件
            this.obtainCanExecuteLocation(publicParam);
            continueExecuFlag = safetyGapOperationService.underImplementationOperation(publicParam.getFlocation(), publicParam.getClocation());
            if (!continueExecuFlag) return;
        });

        // 生成转储
        try {
            execute(() -> {
                boolean isNotCross = publicParam.getFlocation().getCompany().getId().equals(publicParam.getClocation().getCompany().getId());
                List<Map> gapLocationProducts = safetyStockGapRepository.qrySafetyStockGapItem(publicParam.getClocation().getId());
                for (int i = 0, iLen = (int) Math.ceil(Double.valueOf(gapLocationProducts.size()) / 88) ; i < iLen; i++) {
                    safetyGapOperationService.sendDump(i * 88, (i+1) * 88, isNotCross, publicParam);
                }
            });
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

        // 执行完后写入日志
        safetyGapOperationService.executeAfterOperation(publicParam.getFlocation(), publicParam.getClocation());
    }

    // 生成缺口数据
    private void generateGapData(String locationLevelId) {
        List getGaps = safetyStockGapRepository.existsExecuData();
        if (getGaps.isEmpty()) safetyStockGapRepository.exec("BEGIN P_REGIONAL_WAREHOUSE_GAP('" + locationLevelId + "', GET_DATE()); END;");
    }

    private void obtainCanExecuteLocation(PublicParam publicParam) {
        Map findCanExecuteLocation = safetyStockGapRepository.findCanExecuteLocation();
        publicParam.setFlocation(findCanExecuteLocation.get("F_LOCATION_ID").toString());
        publicParam.setClocation(findCanExecuteLocation.get("LOCATION_ID").toString());

        if (StringUtils.isEmpty(publicParam.getExport()) || StringUtils.isEmpty(publicParam.getReception())) {
            safetyGapOperationService.executeAfterOperation(publicParam.getFlocation(), publicParam.getClocation());
        }
    }

    public void execute(Callback callback) {
        transactionTemplate.execute(status -> {
            try {
                callback.execute();
                return null;
            } catch (Exception e) {
                status.isRollbackOnly();
                throw e;
            }
        });
    }

    @FunctionalInterface
    public interface Callback {
        @Nullable
        void execute();
    }

}
